package com.cloud.controller;

import cn.hutool.core.date.DatePattern;
import cn.hutool.json.JSONUtil;
import com.cloud.comm.CommonContext;
import com.cloud.constant.Constants;
import com.cloud.constant.ElasticSearchConstants;
import com.cloud.enums.SupportImportMovieEnum;
import com.cloud.es.ESMoviceInfo;
import com.cloud.factory.ImportMovieFactory;
import com.cloud.factory.MovieInfoFactory;
import com.cloud.job.CacheMovieFilePathJob;
import com.cloud.job.RedisToElasticSearchJob;
import com.cloud.pojo.movie.ImportMovie;
import com.cloud.pojo.movie.MovieAttr;
import com.cloud.pojo.sys.Result;
import com.cloud.service.ImportMovieService;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @version v1.0
 * @author: TianXiang
 * @description:
 * @date: 2020/10/21
 */
@RestController
@RequestMapping("/admin")
public class AdminController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private RestHighLevelClient client;

    @Autowired
    private CacheMovieFilePathJob cacheMovieFilePathJob;

    @Autowired
    private RedisToElasticSearchJob redisToElasticSearchJob;

    private static final Logger LOG = LoggerFactory.getLogger(AdminController.class.getName());

    @GetMapping("ping")
    public void ping() {
        CommonContext context = CommonContext.getContext();
        String dateDir = context.getMoviesPath() + File.separator + DatePattern.PURE_DATE_FORMAT.format(new Date());
        File dateFile = new File(dateDir);
        if(!dateFile.exists()) {
            dateFile.mkdirs();
        }
        File[] dateDirFiles = dateFile.listFiles();
        if(dateDirFiles.length == 1 || dateDirFiles.length == 0) {
            String downloadLinkKey = "use";
            List<Map<String, String>> downloadObjList = new ArrayList<>();
            for(int i = 0; i < 100; i++) {
                String value = redisTemplate.opsForList().rightPop(downloadLinkKey);
                if(StringUtils.isBlank(value)) break;
                downloadObjList.add(JSONUtil.toBean(value, Map.class));
            }
            // 去重变量
            Set<String> set = new HashSet<>();
            ImportMovieService importMovieService = ImportMovieFactory.getStrategyService(SupportImportMovieEnum.URL.getCode());
            downloadObjList.stream().forEach(item -> {
                String title = item.get("title");
                if (!set.contains(title)) {
                    // 下载视频
                    String url = item.get("url");
                    ImportMovie importMovie = new ImportMovie().setDownloadFromUrl(url).setSupportFlag(SupportImportMovieEnum.URL.getCode());
                    importMovie.setMovieName(title);

                    importMovieService.importMovie(importMovie, null, rabbitTemplate, redisTemplate);
                }
                set.add(title);
            });

        }
    }

    @GetMapping("refreshCache")
    public void refreshCache() throws Exception {
        LOG.info("手动刷新缓存");
        cacheMovieFilePathJob.execute();
        redisToElasticSearchJob.execute();
        LOG.info("手动刷新缓存结束");
    }

    @GetMapping("getMovieNameByES")
    @PreAuthorize("hasAuthority('ROLE_VIP')")
    public List<ESMoviceInfo> getMovieNameByES(@RequestParam String keyword,
                                               @RequestParam(required = false, name = "model") String model) throws Exception {
        LOG.info("主动获取播放视频名称关键字: " + keyword);
        if (StringUtils.isBlank(keyword)) return Lists.newArrayList();
        // 查询指定的索引库
        SearchRequest searchRequest;
        if (Constants.GREEN_MODEL.equals(model)) {
            searchRequest = new SearchRequest(ElasticSearchConstants.GREEN_INDEX_LIBRARY_NAME);
        } else {
            searchRequest = new SearchRequest(ElasticSearchConstants.INDEX_LIBRARY_NAME);
        }
        searchRequest.types(ElasticSearchConstants.TABLE_NAME);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 设置起止和结束
        sourceBuilder.from(0);
        sourceBuilder.size(99);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        // 设置查询条件
        sourceBuilder.query(QueryBuilders.wildcardQuery("movieName", String.format("*%s*", keyword)));
        searchRequest.source(sourceBuilder);
        // 设置关键字高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("movieName");
        highlightBuilder.field(highlightTitle);
        sourceBuilder.highlighter(highlightBuilder);
        System.out.println("存在查询的DSL语句:" + sourceBuilder.toString());
        // 同步查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        // 结果
        List<ESMoviceInfo> movieList = Lists.newArrayList();
        searchResponse.getHits().forEach(hit -> {
            Map<String, Object> map = hit.getSourceAsMap();
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            ESMoviceInfo movieInfo = new ESMoviceInfo();
            movieInfo.setMovieName(highlightFields.get("movieName").fragments()[0].string());
            movieInfo.setMovieInfo((String) map.get("movieInfo"));
            movieList.add(movieInfo);
        });
        return movieList;
    }

    @GetMapping("getMovieName")
    @PreAuthorize("hasAuthority('ROLE_VIP')")
    public MovieAttr getMovieName(@RequestParam(required = false, name = "model") String model) {
        MovieAttr movieAttr = MovieInfoFactory.getMovieInfoInRedis(redisTemplate.opsForList(), model);
        LOG.info("获取播放视频名称: " + movieAttr.getMovieName());
        return movieAttr;
    }

    @PostMapping("importMovie")
    public Result importMovie(@RequestParam(value = "uploadFile", required = false) MultipartFile movieFile,
                              ImportMovie importMovie) {
        ImportMovieService importMovieService = ImportMovieFactory.getStrategyService(importMovie.getSupportFlag());
        importMovieService.importMovie(importMovie, movieFile, rabbitTemplate, redisTemplate);
        return Result.createSuccess("转码任务加入到队列成功");
    }

}
